﻿using System;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32.SafeHandles;

namespace CSDisk
{

    public interface IDriveBuffer : IDisposable
    {
        byte[] Buffer
        {
            get;
        }
    }

    public class Drive
    {
        private class DriveBuffer : IDriveBuffer
        {
            private bool _disposed;
            private Drive _parent;

            public DriveBuffer(Drive Parent)
            {
                _parent = Parent;
                _disposed = false;
            }

            public byte[] Buffer
            {
                get
                {
                    if (!_disposed)
                    {
                        return _parent._buffer;
                    }
                    else
                    {
                        return null;
                    }
                }
            }

            public void Dispose()
            {
                Monitor.Exit(_parent);
                _parent = null;
                _disposed = true;
            }
        }

        private bool IsLocked
        {
            get
            {
                return Monitor.IsEntered(this);
            }
        }

        private byte[] _buffer;
        private SafeFileHandle _hDrive;
        private DiskInfo _info;


        [DllImport("kernel32.dll", EntryPoint = "CreateFileW", CharSet = CharSet.Unicode)]
        private static extern Microsoft.Win32.SafeHandles.SafeFileHandle CreateFile(
                [MarshalAs(UnmanagedType.LPWStr)]
                String lpFileName,
                FileAccess dwDesiredAccess,
                ShareModes dwShareMode,
                IntPtr lpSecurityAttributes,
                CreateDisposition dwCreationDisposition,
                FileFlags dwFlagsAndAttributes,
                IntPtr hTemplateFile
                );


        public Drive(DiskInfo info)
        {
            _buffer = new byte[info.DiskGeometry.Geometry.BytesPerSector];
            _info = info;
            _hDrive = CreateFile(info.DevicePath, FileAccess.Read | FileAccess.Write, ShareModes.Read | ShareModes.Write,
                IntPtr.Zero, CreateDisposition.OpenExisting, FileFlags.NoBuffering | FileFlags.RandomAccess | FileFlags.WriteThrough, IntPtr.Zero);
            uint retBytes = 0;
            CSDisk.IoCtl.DeviceIoControl(_hDrive.DangerousGetHandle(), IoCtl.FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, ref retBytes, IntPtr.Zero);
            CSDisk.IoCtl.DeviceIoControl(_hDrive.DangerousGetHandle(), IoCtl.FSCTL_DISMOUNT_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, ref retBytes, IntPtr.Zero);
        }

        public IDriveBuffer Buffer
        {
            get
            {
                if (Monitor.TryEnter(this))
                {
                    return new DriveBuffer(this);
                }
                else
                {
                    return null;
                }
            }
        }

        public void ReadSectorToBuffer(UInt64 sector)
        {
            ulong newPtr;
            uint bytesRead;
            if (Monitor.TryEnter(this))
            {
            //    FileIO.SetFilePointerEx(_hDrive.DangerousGetHandle(), sector * _info.BytesPerSector, out newPtr, FileIO.SeekMethod.Begin);
           //     FileIO.ReadFile(_hDrive.DangerousGetHandle(), _buffer, (uint)_buffer.Length, out bytesRead, IntPtr.Zero);
                Monitor.Exit(this);
            }
        }

        public void WriteBufferToSector(UInt64 sector)
        {
            ulong newPtr;
            uint bytesWritten;
            if (Monitor.TryEnter(this))
            {
             //   FileIO.SetFilePointerEx(_hDrive.DangerousGetHandle(), sector * _info.BytesPerSector, out newPtr, FileIO.SeekMethod.Begin);
             //   FileIO.WriteFile(_hDrive.DangerousGetHandle(), _buffer, (uint)_buffer.Length, out bytesWritten, IntPtr.Zero);
                Monitor.Exit(this);
            }
        }

    }

}





using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace CSDisk
{
    // Note: When you instantiate a structure like this, all of the functions of all of the instances are shared.

    // Functions are not copied into new instances for each instance of the structure.  
    // Rather, the structure, itself, is treated as an implicit argument to each function, 

    // and each function is actually declared as static in memory.
    // Therefore, each new instance of a structure like this, as vast and stupendous as it may seem,
    // is only sizeof(IntPtr).

    // This is true in C#, C++/CLI and Visual Basic.  This is universal.

    // I don't know if the same is true of classes, but something off the top of my head tells me it is.

    // But I definitely know it's true of structures.

    // This structure is a Swiss-Army-Knife of p/Invoke.

    // There wasn't one, so I invented it.  I did it for VB because I am
    // programming in VB. 

    // But, you gave me a reason to port (much) of it to C#.

    // Believe me when I tell you, this is an abbreviated edition of this structure. 

    #region oldcode

    //    /// <summary>
    //    ///
    //    /// Lightweight utility structure with a solitary IntPtr field.
    //    /// Can be used in place of IntPtr on all p/Invoke calls.
    //    ///
    //    /// !!! Note: Completely unmanaged. You must free what you allocate !!!
    //    ///
    //    /// </summary>
    //    [StructLayout(LayoutKind.Sequential)]
    //    public struct MemPtr
    //    {
    //        private const string MemTooBig = "The logical maximum index of the buffer is too large to declare a managed array (Greater Than Int32.MaxValue).";

    //        private const string NoPtr = "The pointer is uninitialized.";

    //        private const string BuffTooSmall = "The buffer cannot take the amount of data in the array at the specified position.";

    //        #region CopyMemory Declares

    //        // Pointer to Pointer

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, IntPtr src, IntPtr byteLen);

    //        // String

    //        [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    //        private static extern void CopyMemory(string dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    //        private static extern void CopyMemory(IntPtr dest, string src, IntPtr byteLen);

    //        // Arrays

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U2)] char[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, char[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1)] sbyte[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, sbyte[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)] byte[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, byte[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I8)] long[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, long[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U8)] ulong[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ulong[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I4)] int[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, int[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] uint[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, uint[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I2)] short[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, short[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U2)] ushort[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ushort[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] float[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, float[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U8)] double[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, double[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct)] decimal[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, decimal[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.Struct)] Guid[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, Guid[] src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
    //        private static extern void CopyMemory([Out, MarshalAs(UnmanagedType.Struct)] DateTime[] dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, DateTime[] src, IntPtr byteLen);

    //        // Scalars

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref char dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref char src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref sbyte dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref sbyte src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref byte dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref byte src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref long dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref long src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref ulong dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref ulong src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref int dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref int src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref uint dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref uint src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref short dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref short src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref ushort dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref ushort src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref float dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref float src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref double dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref double src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref decimal dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref decimal src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(ref Guid dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint="RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref Guid src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
    //        private static extern void CopyMemory(ref DateTime dest, IntPtr src, IntPtr byteLen);

    //        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
    //        private static extern void CopyMemory(IntPtr dest, ref DateTime src, IntPtr byteLen);

    //        #endregion CopyMemory Declares

    //        /// <summary>
    //        /// The solitary variable in this structure.
    //        /// This allows this structure to be used in place of IntPtr in all p/Invoke calls.
    //        /// </summary>
    //        private IntPtr _ptr;

    //        /// <summary>
    //        /// Returns INVALID_HANDLE_VALUE (-1)
    //        /// </summary>
    //        public static readonly MemPtr InvalidHandle = new MemPtr((IntPtr)(int)-1);

    //        /// <summary>
    //        /// Returns a null pointer.
    //        /// </summary>
    //        public static readonly MemPtr Empty = new MemPtr((IntPtr)0);

    //        /// <summary>
    //        /// Gets or sets the handle to the unmanaged memory.
    //        /// </summary>
    //        public IntPtr Handle
    //        {
    //            get
    //            {
    //                return _ptr;
    //            }
    //            set
    //            {
    //                if (_ptr != IntPtr.Zero)
    //                {
    //                    if (!Free()) return;
    //                }
    //                _ptr = value;
    //            }
    //        }

    //        #region Structures

    //        /// <summary>
    //        /// Retrieves the specified structure at the specified byteIndex.
    //        /// </summary>
    //        /// <typeparam name="T">Type of structure to retrieve.</typeparam>
    //        /// <param name="byteIndex">Index at which to start copying.</param>
    //        /// <returns>T</returns>
    //        public T StructAt<T>(long byteIndex) where T: struct
    //        {
    //            if (_ptr == IntPtr.Zero) return new T();

    //            T s = new T();
    //            int x = Marshal.SizeOf(s);

    //            IntPtr p = new IntPtr(_ptr.ToInt64() + byteIndex);
    //            s = (T)Marshal.PtrToStructure(p, typeof(T));
    //            return s;
    //        }

    //        /// <summary>
    //        /// Sets the specified structure at the specified byte index.
    //        /// </summary>
    //        /// <typeparam name="T">Type of structure to retrieve.</typeparam>
    //        /// <param name="byteIndex">Index at which to start copying.</param>
    //        /// <param name="val">Structure to copy.</param>
    //        public void StructAt<T>(long byteIndex, T val) where T : struct
    //        {
    //            if (_ptr == IntPtr.Zero) return;

    //            int sx = Marshal.SizeOf(val);

    //            long x = this.GetLength();
    //            long y = byteIndex + sx;

    //            if (y > x) throw new ArgumentOutOfRangeException(BuffTooSmall);
    //            IntPtr p = new IntPtr(_ptr.ToInt64() + byteIndex);

    //            Marshal.StructureToPtr((object) val, p, false);
    //        }

    //        /// <summary>
    //        /// Sets this pointer to the specified structure.
    //        /// </summary>
    //        /// <typeparam name="T">Type of structure to set.</typeparam>
    //        /// <param name="val">Structure to copy.</param>
    //        public void FromStruct<T>(T val) where T : struct
    //        {
    //            if (_ptr != IntPtr.Zero) if (!Free()) return;
    //            int sx = Marshal.SizeOf(val);
    //            Alloc(sx);             
    //            Marshal.StructureToPtr((object)val, _ptr, false);
    //        }

    //        /// <summary>
    //        /// Gets the structure pointed to by this buffer.
    //        /// </summary>
    //        /// <typeparam name="T">Type of structure to retrieve.</typeparam>
    //        /// <returns></returns>
    //        public T ToStruct<T>() where T : struct
    //        {
    //            return this.StructAt<T>(0);
    //        }

    //        #endregion

    //        // String utility functions to the various types.
    //        // Those types being: Utf16 (normal wchar) strings, Utf8 strings, Ascii strings and Byte[].
    //        #region Bytes and Strings

    //        /// <summary>
    //        /// Finds a null-terminated Utf16 string starting at the specified byteIndex and returns a String.
    //        /// </summary>
    //        /// <param name="byteIndex"></param>
    //        /// <returns></returns>
    //        public string GrabString(long byteIndex)
    //        {
    //            if (_ptr == IntPtr.Zero) return null;

    //            char ch = (char)0;
    //            char[] outch;
    //            int x;

    //            IntPtr p = new IntPtr(_ptr.ToInt64() + byteIndex);
    //            IntPtr bp = p;

    //            IntPtr chSize = new IntPtr(2);

    //            do
    //            {
    //                CopyMemory(ref ch, p, chSize);
    //                if (ch != (char)0) p += 2;
    //            } while (ch != (char)0);

    //            x = (int)(p.ToInt64() - bp.ToInt64());
    //            x = (x / 2);

    //            outch = new char[x];

    //            CopyMemory(outch, bp, (IntPtr)(x * 2));
    //            return new String(outch);
    //        }

    //        /// <summary>
    //        /// Grabs a Utf16 string starting at the specified byteIndex with the specified character length.
    //        /// No null termination checking is performed.
    //        /// </summary>
    //        /// <param name="byteIndex">The byte index at which to begin copying.</param>
    //        /// <param name="length">The number of Utf16 characters to copy.</param>
    //        /// <returns></returns>
    //        public string GrabString(long byteIndex, int length)
    //        {
    //            if (_ptr == IntPtr.Zero) return null;

    //            string s = new string((char)0, length);
    //            CopyMemory(s, (IntPtr)(_ptr.ToInt64() + byteIndex), (IntPtr)(length * 2));
    //            return s;
    //        }

    //        /// <summary>
    //        /// Grabs an Ascii or Utf8 string starting at the specified byteIndex with the specified byte length.
    //        /// No null termination checking is performed.
    //        /// </summary>
    //        /// <param name="byteIndex">The byte index at which to begin copying.</param>
    //        /// <param name="length">The number of bytes to copy.</param>
    //        /// <returns></returns>
    //        public string GrabUtf8String(long byteIndex, int length)
    //        {
    //            if (_ptr == IntPtr.Zero) return null;

    //            byte[] s = new byte[length];
    //            CopyMemory(s, (IntPtr)(_ptr.ToInt64() + byteIndex), (IntPtr)length);
    //            return System.Text.Encoding.UTF8.GrabString(s);
    //        }

    //        /// <summary>
    //        /// Finds a null-terminated Ascii or Utf8 string starting at the specified byteIndex and returns a String.
    //        /// </summary>
    //        /// <param name="byteIndex"></param>
    //        /// <returns></returns>
    //        public string GrabUtf8String(long byteIndex)
    //        {
    //            if (_ptr == IntPtr.Zero) return null;

    //            byte ch = 0;
    //            byte[] outch;
    //            int x;

    //            IntPtr p = new IntPtr(_ptr.ToInt64() + byteIndex);
    //            IntPtr bp = p;
    //            IntPtr chSize = new IntPtr(1);

    //            do
    //            {
    //                CopyMemory(ref ch, p, chSize);
    //                if (ch != 0) p += 1;
    //            } while (ch != 0);

    //            x = (int)(p.ToInt64() - bp.ToInt64());

    //            outch = new byte[x];

    //            CopyMemory(outch, bp, (IntPtr)(x));
    //            return System.Text.Encoding.UTF8.GrabString(outch);
    //        }

    //        /// <summary>
    //        /// Grabs a BSTR-style COM string from the specified byte index.
    //        /// </summary>
    //        /// <param name="byteIndex">Index at which to begin copying.</param>
    //        /// <param name="comptr">Specifies whether this is an actual COM pointer.</param>
    //        /// <returns></returns>
    //        public string GrabBSTR(long byteIndex = 0, bool comptr = true)
    //        {
    //            IntPtr p = (comptr ? new IntPtr(_ptr.ToInt64() + byteIndex - 4) : new IntPtr(_ptr.ToInt64() + byteIndex));
    //            int i = 0;
    //            string s;

    //            CopyMemory(ref i, p, (IntPtr)4);
    //            s = new string((char)0, i * 2);

    //            CopyMemory(s, (IntPtr)(p + 4), (IntPtr)(i * 2));
    //            return s;
    //        }


    //        /// <summary>
    //        /// Returns the string array at the byteIndex.
    //        /// </summary>
    //        /// <param name="byteIndex">Index at which to start copying.</param>
    //        /// <returns></returns>
    //        public string[] GrabStringArray(long byteIndex)
    //        {
    //            if (_ptr == IntPtr.Zero) return null;

    //            char ch = (char)0;
    //            string s = null;

    //            IntPtr cp = new IntPtr(_ptr.ToInt64() + byteIndex);
    //            IntPtr ap = cp;

    //            int x = 0;

    //            List<string> o = new List<string>();

    //            while (true)
    //            {

    //                CopyMemory(ref ch, ap, (IntPtr)2);
    //                if (ch == (char)0)
    //                {
    //                    if (x != 0)
    //                    {
    //                        s = new String((char)0, x);
    //                        CopyMemory(s, cp, (IntPtr)(x * 2));
    //                        o.Add(s);

    //                        s = null;
    //                        x = 0;
    //                        cp = ap + 2;
    //                        ap = cp;

    //                    }
    //                    else
    //                    {
    //                        break;
    //                    }
    //                }
    //                else
    //                {
    //                    x++;
    //                    ap += 2;
    //                }
    //            }

    //            return o.ToArray();
    //        }

    //        /// <summary>
    //        /// Returns the byte array at the specified index with the specified length.
    //        /// </summary>
    //        /// <param name="byteIndex">Index at which to begin copying.</param>
    //        /// <param name="length">Number of bytes to return.</param>
    //        /// <returns></returns>
    //        public byte[] GrabBytes(long byteIndex, long length = -1)
    //        {
    //            if (_ptr == IntPtr.Zero) return null;

    //            if (length == -1) length = this.GetLength();

    //            byte[] by = new byte[length];
    //            IntPtr p = new IntPtr(_ptr.ToInt64() + byteIndex);

    //            CopyMemory(by, p, (IntPtr)length);

    //            return by;
    //        }

    //        public void SetBytes(long byteIndex, byte[] data)
    //        {
    //            if (_ptr == IntPtr.Zero) throw new ArgumentNullException(NoPtr);

    //            long x = this.GetLength();
    //            long y = byteIndex + data.Length;

    //            if (y > x) throw new ArgumentOutOfRangeException(BuffTooSmall);
    //        }

    //        #endregion Bytes and Strings

    //        // Indexers to the various types.
    //        // Those types being: byte, sbyte, short, ushort, int, uint, long, ulong, float, double, decimal, Guid, and DateTime.
    //        #region Indexers

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public byte byteAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            byte x = 0;

    //            CopyMemory(ref x, p, (IntPtr)1);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void byteAt(long index, byte value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            byte x = value;

    //            CopyMemory(p, ref x, (IntPtr)1);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public sbyte sbyteAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            sbyte x = 0;

    //            CopyMemory(ref x, p, (IntPtr)1);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void sbyteAt(long index, sbyte value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            sbyte x = value;

    //            CopyMemory(p, ref x, (IntPtr)1);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public char charAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            char x = (char)0;

    //            CopyMemory(ref x, p, (IntPtr)2);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void charAt(long index, char value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            char x = value;

    //            CopyMemory(p, ref x, (IntPtr)2);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public ushort ushortAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            ushort x = 0;

    //            CopyMemory(ref x, p, (IntPtr)2);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void ushortAt(long index, ushort value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            ushort x = value;

    //            CopyMemory(p, ref x, (IntPtr)2);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public short shortAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            short x = 0;

    //            CopyMemory(ref x, p, (IntPtr)2);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void shortAt(long index, short value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            short x = value;

    //            CopyMemory(p, ref x, (IntPtr)2);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public uint uintAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            uint x = 0;

    //            CopyMemory(ref x, p, (IntPtr)4);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void uintAt(long index, uint value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            uint x = value;

    //            CopyMemory(p, ref x, (IntPtr)4);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public int intAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            int x = 0;

    //            CopyMemory(ref x, p, (IntPtr)4);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void intAt(long index, int value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            int x = value;

    //            CopyMemory(p, ref x, (IntPtr)4);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public ulong ulongAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            ulong x = 0;

    //            CopyMemory(ref x, p, (IntPtr)8);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void ulongAt(long index, ulong value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            ulong x = value;

    //            CopyMemory(p, ref x, (IntPtr)8);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public long longAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            long x = 0;

    //            CopyMemory(ref x, p, (IntPtr)8);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void longAt(long index, long value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            long x = value;

    //            CopyMemory(p, ref x, (IntPtr)8);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public float floatAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            float x = 0;

    //            CopyMemory(ref x, p, (IntPtr)4);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void floatAt(long index, float value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            float x = value;

    //            CopyMemory(p, ref x, (IntPtr)4);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public double doubleAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            double x = 0;

    //            CopyMemory(ref x, p, (IntPtr)8);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void doubleAt(long index, double value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            double x = value;

    //            CopyMemory(p, ref x, (IntPtr)8);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public decimal decimalAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            decimal x = 0;

    //            CopyMemory(ref x, p, (IntPtr)16);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void decimalAt(long index, decimal value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            decimal x = value;

    //            CopyMemory(p, ref x, (IntPtr)16);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public Guid GuidAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            Guid x = Guid.Empty;

    //            CopyMemory(ref x, p, (IntPtr)16);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void GuidAt(long index, Guid value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            Guid x = value;

    //            CopyMemory(p, ref x, (IntPtr)16);
    //        }

    //        /// <summary>
    //        /// Returns the value in the buffer at the specified index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <returns></returns>
    //        public DateTime DateTimeAt(long index)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            DateTime x = DateTime.Now;

    //            CopyMemory(ref x, p, (IntPtr)8);
    //            return x;
    //        }

    //        /// <summary>
    //        /// Sets the buffer to the specified value at the specified byte index.
    //        /// </summary>
    //        /// <param name="index">Index at which to start copying the value.</param>
    //        /// <param name="value">Value to copy.</param>
    //        public void DateTimeAt(long index, DateTime value)
    //        {
    //            IntPtr p = new IntPtr(index + _ptr.ToInt64());
    //            DateTime x = value;

    //            CopyMemory(p, ref x, (IntPtr)8);
    //        }

    //        #endregion Indexers

    //        // Operators to implicitly convert between the various types.
    //        // Those types being: byte, sbyte, short, ushort, int, uint, long, ulong, float, double, decimal, Guid, and DateTime.
    //        #region Cast Operators

    //        // pointers

    //        public static implicit operator UIntPtr(MemPtr operand)
    //        {
    //            return (UIntPtr)(ulong)operand._ptr.ToInt64();
    //        }

    //        public static implicit operator MemPtr(UIntPtr operand)
    //        {
    //            return new MemPtr((IntPtr)operand.ToUInt64());
    //        }

    //        public static implicit operator IntPtr(MemPtr operand)
    //        {
    //            return operand._ptr;
    //        }

    //        public static implicit operator MemPtr(IntPtr operand)
    //        {
    //            return new MemPtr(operand);
    //        }

    //        // strings

    //        public static implicit operator string(MemPtr operand)
    //        {
    //            return operand.GrabString(0);
    //        }

    //        public static implicit operator MemPtr(string operand)
    //        {
    //            MemPtr mm = new MemPtr((operand.Length * 2) + 2);
    //            CopyMemory(mm.Handle, operand, new IntPtr(operand.Length * 2));
    //            return mm;
    //        }

    //        // buffers

    //        public static implicit operator byte[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength();
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            byte[] o = new byte[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(byte[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length));
    //            return mm;
    //        }

    //        public static implicit operator sbyte[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength();
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            sbyte[] o = new sbyte[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(sbyte[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length));
    //            return mm;
    //        }

    //        public static implicit operator short[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength() / 2;
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            short[] o = new short[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x * 2));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(short[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length * 2);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length * 2));
    //            return mm;
    //        }

    //        public static implicit operator ushort[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength() / 2;
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            ushort[] o = new ushort[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x * 2));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(ushort[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length * 2);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length * 2));
    //            return mm;
    //        }

    //        public static implicit operator int[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength() / 4;
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            int[] o = new int[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x * 4));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(int[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length * 4);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length * 4));
    //            return mm;
    //        }

    //        public static implicit operator uint[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength() / 4;
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            uint[] o = new uint[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x * 4));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(uint[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length * 4);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length * 4));
    //            return mm;
    //        }

    //        public static implicit operator long[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength() / 8;
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            long[] o = new long[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x * 8));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(long[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length * 8);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length * 8));
    //            return mm;
    //        }

    //        public static implicit operator ulong[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength() / 8;
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            ulong[] o = new ulong[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x * 8));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(ulong[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length * 8);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length * 8));
    //            return mm;
    //        }

    //        public static implicit operator float[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength() / 4;
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            float[] o = new float[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x * 4));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(float[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length * 4);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length * 4));
    //            return mm;
    //        }

    //        public static implicit operator double[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength() / 8;
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            double[] o = new double[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x * 8));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(double[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length * 8);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length * 8));
    //            return mm;
    //        }

    //        public static implicit operator decimal[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength() / 16;
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            decimal[] o = new decimal[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x * 16));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(decimal[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length * 16);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length * 16));
    //            return mm;
    //        }

    //        public static implicit operator Guid[](MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return null;
    //            long x = operand.GetLength() / 16;
    //            if (x > Int32.MaxValue)
    //            {
    //                throw new InsufficientMemoryException(MemTooBig);
    //            }

    //            Guid[] o = new Guid[x];
    //            CopyMemory(o, operand._ptr, (IntPtr)(x * 16));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(Guid[] operand)
    //        {
    //            MemPtr mm = new MemPtr(operand.Length * 16);
    //            CopyMemory(mm.Handle, operand, (IntPtr)(operand.Length * 16));
    //            return mm;
    //        }

    //        // singletons

    //        public static implicit operator byte(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            byte o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(1));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(byte operand)
    //        {
    //            MemPtr mm = new MemPtr(1);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(1));
    //            return mm;
    //        }

    //        public static implicit operator sbyte(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            sbyte o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(1));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(sbyte operand)
    //        {
    //            MemPtr mm = new MemPtr(1);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(1));
    //            return mm;
    //        }

    //        public static implicit operator short(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            short o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(2));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(short operand)
    //        {
    //            MemPtr mm = new MemPtr(2);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(2));
    //            return mm;
    //        }

    //        public static implicit operator ushort(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            ushort o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(2));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(ushort operand)
    //        {
    //            MemPtr mm = new MemPtr(2);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(2));
    //            return mm;
    //        }

    //        public static implicit operator int(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            int o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(4));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(int operand)
    //        {
    //            MemPtr mm = new MemPtr(4);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(4));
    //            return mm;
    //        }

    //        public static implicit operator uint(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            uint o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(4));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(uint operand)
    //        {
    //            MemPtr mm = new MemPtr(4);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(4));
    //            return mm;
    //        }

    //        public static implicit operator long(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            long o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(8));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(long operand)
    //        {
    //            MemPtr mm = new MemPtr(8);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(8));
    //            return mm;
    //        }

    //        public static implicit operator ulong(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            ulong o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(8));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(ulong operand)
    //        {
    //            MemPtr mm = new MemPtr(8);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(8));
    //            return mm;
    //        }

    //        public static implicit operator float(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            float o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(4));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(float operand)
    //        {
    //            MemPtr mm = new MemPtr(4);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(4));
    //            return mm;
    //        }

    //        public static implicit operator double(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            double o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(8));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(double operand)
    //        {
    //            MemPtr mm = new MemPtr(8);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(8));
    //            return mm;
    //        }

    //        public static implicit operator decimal(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return 0;

    //            decimal o = 0;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(16));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(decimal operand)
    //        {
    //            MemPtr mm = new MemPtr(16);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(16));
    //            return mm;
    //        }

    //        public static implicit operator Guid(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return Guid.Empty;

    //            Guid o = Guid.Empty;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(16));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(Guid operand)
    //        {
    //            MemPtr mm = new MemPtr(16);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(16));
    //            return mm;
    //        }

    //        public static implicit operator DateTime(MemPtr operand)
    //        {
    //            if (operand._ptr == IntPtr.Zero) return DateTime.Now;

    //            DateTime o = DateTime.Now;
    //            CopyMemory(ref o, operand._ptr, (IntPtr)(8));
    //            return o;
    //        }

    //        public static implicit operator MemPtr(DateTime operand)
    //        {
    //            MemPtr mm = new MemPtr(8);
    //            CopyMemory(mm.Handle, ref operand, (IntPtr)(8));
    //            return mm;
    //        }

    //        #endregion Cast Operators

    //        // Comparison operators between MemPtr, IntPtr, and UIntPtr
    //        #region Comparison Operators

    //        public static bool operator ==(MemPtr operand1, MemPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() == operand2._ptr.ToInt64());
    //        }

    //        public static bool operator !=(MemPtr operand1, MemPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() != operand2._ptr.ToInt64());
    //        }

    //        public static bool operator >=(MemPtr operand1, MemPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() >= operand2._ptr.ToInt64());
    //        }

    //        public static bool operator <=(MemPtr operand1, MemPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() <= operand2._ptr.ToInt64());
    //        }

    //        public static bool operator >(MemPtr operand1, MemPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() > operand2._ptr.ToInt64());
    //        }

    //        public static bool operator <(MemPtr operand1, MemPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() < operand2._ptr.ToInt64());
    //        }


    //        public static bool operator ==(MemPtr operand1, IntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() == operand2.ToInt64());
    //        }

    //        public static bool operator !=(MemPtr operand1, IntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() != operand2.ToInt64());
    //        }

    //        public static bool operator >=(MemPtr operand1, IntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() >= operand2.ToInt64());
    //        }

    //        public static bool operator <=(MemPtr operand1, IntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() <= operand2.ToInt64());
    //        }

    //        public static bool operator >(MemPtr operand1, IntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() > operand2.ToInt64());
    //        }

    //        public static bool operator <(MemPtr operand1, IntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() < operand2.ToInt64());
    //        }

    //        public static bool operator ==(MemPtr operand1, UIntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() == (long) operand2.ToUInt64());
    //        }

    //        public static bool operator !=(MemPtr operand1, UIntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() != (long)operand2.ToUInt64());
    //        }

    //        public static bool operator >=(MemPtr operand1, UIntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() >= (long)operand2.ToUInt64());
    //        }

    //        public static bool operator <=(MemPtr operand1, UIntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() <= (long)operand2.ToUInt64());
    //        }

    //        public static bool operator >(MemPtr operand1, UIntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() > (long)operand2.ToUInt64());
    //        }

    //        public static bool operator <(MemPtr operand1, UIntPtr operand2)
    //        {
    //            return (operand1._ptr.ToInt64() < (long)operand2.ToUInt64());
    //        }

    //        public static bool operator ==(IntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToInt64() == (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator !=(IntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToInt64() != (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator >=(IntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToInt64() >= (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator <=(IntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToInt64() <= (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator >(IntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToInt64() > (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator <(IntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToInt64() < (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator ==(UIntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToUInt64() == (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator !=(UIntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToUInt64() != (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator >=(UIntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToUInt64() >= (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator <=(UIntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToUInt64() <= (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator >(UIntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToUInt64() > (long)operand2._ptr.ToInt64());
    //        }

    //        public static bool operator <(UIntPtr operand1, MemPtr operand2)
    //        {
    //            return ((long)operand1.ToUInt64() < (long)operand2._ptr.ToInt64());
    //        }


    //        #endregion

    //        // Pointer arithmatic
    //        #region Pointer Arithmatic Operators

    //        public static MemPtr operator +(MemPtr operand1, MemPtr operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() + operand2._ptr.ToInt64()));
    //        }

    //        public static MemPtr operator -(MemPtr operand1, MemPtr operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() - operand2._ptr.ToInt64()));
    //        }

    //        public static MemPtr operator *(MemPtr operand1, MemPtr operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() * operand2._ptr.ToInt64()));
    //        }

    //        public static MemPtr operator /(MemPtr operand1, MemPtr operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() / operand2._ptr.ToInt64()));
    //        }

    //        public static MemPtr operator %(MemPtr operand1, MemPtr operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() % operand2._ptr.ToInt64()));
    //        }



    //        public static MemPtr operator +(MemPtr operand1, short operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() + operand2));
    //        }

    //        public static MemPtr operator -(MemPtr operand1, short operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() - operand2));
    //        }

    //        public static MemPtr operator *(MemPtr operand1, short operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() * operand2));
    //        }

    //        public static MemPtr operator /(MemPtr operand1, short operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() / operand2));
    //        }

    //        public static MemPtr operator %(MemPtr operand1, short operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() % operand2));
    //        }


    //        public static MemPtr operator +(MemPtr operand1, ushort operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() + operand2));
    //        }

    //        public static MemPtr operator -(MemPtr operand1, ushort operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() - operand2));
    //        }

    //        public static MemPtr operator *(MemPtr operand1, ushort operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() * operand2));
    //        }

    //        public static MemPtr operator /(MemPtr operand1, ushort operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() / operand2));
    //        }

    //        public static MemPtr operator %(MemPtr operand1, ushort operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() % operand2));
    //        }



    //        public static MemPtr operator +(MemPtr operand1, int operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() + operand2));
    //        }

    //        public static MemPtr operator -(MemPtr operand1, int operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() - operand2));
    //        }

    //        public static MemPtr operator *(MemPtr operand1, int operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() * operand2));
    //        }

    //        public static MemPtr operator /(MemPtr operand1, int operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() / operand2));
    //        }

    //        public static MemPtr operator %(MemPtr operand1, int operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() % operand2));
    //        }


    //        public static MemPtr operator +(MemPtr operand1, uint operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() + operand2));
    //        }

    //        public static MemPtr operator -(MemPtr operand1, uint operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() - operand2));
    //        }

    //        public static MemPtr operator *(MemPtr operand1, uint operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() * operand2));
    //        }

    //        public static MemPtr operator /(MemPtr operand1, uint operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() / operand2));
    //        }

    //        public static MemPtr operator %(MemPtr operand1, uint operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() % operand2));
    //        }



    //        public static MemPtr operator +(MemPtr operand1, long operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() + operand2));
    //        }

    //        public static MemPtr operator -(MemPtr operand1, long operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() - operand2));
    //        }

    //        public static MemPtr operator *(MemPtr operand1, long operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() * operand2));
    //        }

    //        public static MemPtr operator /(MemPtr operand1, long operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() / operand2));
    //        }

    //        public static MemPtr operator %(MemPtr operand1, long operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() % operand2));
    //        }

    //        public static MemPtr operator +(MemPtr operand1, ulong operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() + (long)operand2));
    //        }

    //        public static MemPtr operator -(MemPtr operand1, ulong operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() - (long)operand2));
    //        }

    //        public static MemPtr operator *(MemPtr operand1, ulong operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() * (long)operand2));
    //        }

    //        public static MemPtr operator /(MemPtr operand1, ulong operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() / (long)operand2));
    //        }

    //        public static MemPtr operator %(MemPtr operand1, ulong operand2)
    //        {
    //            return new MemPtr(new IntPtr(operand1._ptr.ToInt64() % (long) operand2));
    //        }


    //        #endregion

    //        #region Instantiation

    //        /// <summary>
    //        /// Initialize a new MemPtr structure with the specified IntPtr value.
    //        /// </summary>
    //        /// <param name="h">IntPtr value.</param>
    //        public MemPtr(IntPtr h)
    //        {
    //            _ptr = h;
    //        }

    //        /// <summary>
    //        /// Initialize a new MemPtr structure with the specified UIntPtr value.
    //        /// </summary>
    //        /// <param name="h">IntPtr value.</param>
    //        public MemPtr(UIntPtr h)
    //        {
    //            _ptr = (IntPtr)(long)h.ToUInt64();
    //        }

    //        /// <summary>
    //        /// Allocate a block of memory with the given size.
    //        /// </summary>
    //        /// <param name="size">Size of the memory block to allocate.</param>
    //        public MemPtr(int size)
    //        {
    //            _ptr = IntPtr.Zero;
    //            Alloc(size);
    //        }

    //        /// <summary>
    //        /// Allocate a block of memory with the given size.
    //        /// </summary>
    //        /// <param name="size">Size of the memory block to allocate.</param>
    //        public MemPtr(uint size)
    //        {
    //            _ptr = IntPtr.Zero;
    //            Alloc(size);
    //        }

    //        /// <summary>
    //        /// Allocate a block of memory with the given size.
    //        /// </summary>
    //        /// <param name="size">Size of the memory block to allocate.</param>
    //        public MemPtr(long size)
    //        {
    //            _ptr = IntPtr.Zero;
    //            Alloc(size);
    //        }

    //        #endregion Instantiation

    //        #region Allocation

    //        [DllImport("kernel32.dll")]
    //        private static extern IntPtr HeapAlloc(IntPtr hHeap, uint Flags, IntPtr size);

    //        [DllImport("kernel32.dll")]
    //        private static extern IntPtr GetProcessHeap();

    //        [DllImport("kernel32.dll")]
    //        private static extern IntPtr HeapReAlloc(IntPtr hHeap, uint Flags, IntPtr oldPtr, IntPtr newSize);

    //        [DllImport("kernel32.dll")]
    //        private static extern bool HeapFree(IntPtr hHeap, uint Flags, IntPtr ptr);

    //        [DllImport("kernel32.dll")]
    //        private static extern IntPtr HeapSize(IntPtr hHeap, uint Flags, IntPtr ptr);

    //        /// <summary>
    //        /// Gets the length of the currently allocated block of memory.
    //        /// This should only be called by a pointer that you know indicates the beginning of a
    //        /// block of memory allocated on the process heap.
    //        /// </summary>
    //        /// <returns></returns>
    //        public long GetLength()
    //        {
    //            if (_ptr == IntPtr.Zero) return 0;
    //            return HeapSize(GetProcessHeap(), 0, _ptr).ToInt64();
    //        }

    //        /// <summary>
    //        /// Allocates a block of memory on the process heap.
    //        /// </summary>
    //        /// <param name="size">Size of the buffer to allocate.</param>
    //        /// <returns>True if successful.</returns>
    //        public bool Alloc(long size)
    //        {
    //            if (_ptr != IntPtr.Zero)
    //            {
    //                if (size == GetLength()) return true;
    //                return ReAlloc(size);
    //            }

    //            IntPtr hheap = GetProcessHeap();
    //            _ptr = HeapAlloc(hheap, 8, new IntPtr(size));
    //            if (_ptr == IntPtr.Zero) return false;
    //            return true;
    //        }

    //        /// <summary>
    //        /// Reallocate a block of memory on the process heap.
    //        /// </summary>
    //        /// <param name="size">New size of the memory block.</param>
    //        /// <returns>True if successful.</returns>
    //        public bool ReAlloc(long size)
    //        {
    //            if (_ptr == IntPtr.Zero) return Alloc(size);

    //            if (GetLength() == size) return true;

    //            IntPtr hheap = GetProcessHeap();
    //            IntPtr n;

    //            n = HeapReAlloc(hheap, 8, _ptr, new IntPtr(size));
    //            if (n == IntPtr.Zero) return false;

    //            _ptr = n;
    //            return true;
    //        }

    //        /// <summary>
    //        /// Frees a previously allocated block of memory.
    //        /// </summary>
    //        /// <returns></returns>
    //        public bool Free()
    //        {
    //            if (_ptr == IntPtr.Zero) return true;

    //            IntPtr hheap = GetProcessHeap();
    //            if (HeapFree(hheap, 0, _ptr))
    //            {
    //                _ptr = IntPtr.Zero;
    //                return true;
    //            }
    //            return false;
    //        }

    //        /// <summary>
    //        /// Frees a block of memory previously allocated by COM.
    //        /// </summary>
    //        public void CoTaskMemFree()
    //        {
    //            if (_ptr == IntPtr.Zero) return;
    //            Marshal.FreeCoTaskMem(_ptr);
    //            _ptr = IntPtr.Zero;
    //        }

    //        #endregion Allocation

    //        #region Overrides

    //        /// <summary>
    //        /// Interprets the block of memory as an LPWSTR and returns a new string.
    //        /// </summary>
    //        /// <returns></returns>
    //        public override string ToString()
    //        {
    //            return (string)this;
    //        }

    //        /// <summary>
    //        /// Test whether this instance is equal to obj.
    //        /// </summary>
    //        /// <param name="obj">Object to compare.</param>
    //        /// <returns></returns>
    //        public override bool Equals(object obj)
    //        {
    //            if (obj.GetType() != typeof(MemPtr))
    //            {
    //                if (obj.GetType() == typeof(IntPtr))
    //                {
    //                    return ((IntPtr)obj) == _ptr;
    //                }
    //                else if (obj.GetType() == typeof(UIntPtr))
    //                {
    //                    return ((UIntPtr)obj).ToUInt64() == (ulong) _ptr.ToInt64();
    //                }
    //                else
    //                {
    //                    return false;
    //                }
    //            }
    //            return ((MemPtr)(obj))._ptr == this._ptr;
    //        }

    //        public override int GetHashCode()
    //        {
    //            return (int)(_ptr.ToInt64() >> 8);
    //        }

    //        #endregion
    //    }

    #endregion

    #region newcode

    /// <summary>
    /// MemPtr interop pointer structure.
    /// </summary>
    public struct MemPtr
    {
        private unsafe void* _ptr;

        /// <summary>
        /// Returns INVALID_HANDLE_VALUE (-1)
        /// </summary>
        public static readonly MemPtr InvalidHandle = new MemPtr((IntPtr)(int)-1);

        /// <summary>
        /// Returns a null pointer.
        /// </summary>
        public static readonly MemPtr Empty = new MemPtr((IntPtr)0);

        #region CopyMemory

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, void* src, long length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPWStr)] string src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPWStr)] string dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] byte[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] byte[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] sbyte[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] sbyte[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] char[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] char[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] short[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] short[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] ushort[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] ushort[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] int[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] int[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] uint[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] uint[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] long[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] long[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] ulong[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] ulong[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] float[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] float[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] double[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] double[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] decimal[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] decimal[] dest, void* src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory(void* dest, [In, MarshalAs(UnmanagedType.LPArray)] Guid[] src, IntPtr length);

        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        internal unsafe static extern void CopyMemory([Out, MarshalAs(UnmanagedType.LPArray)] Guid[] dest, void* src, IntPtr length);

        #endregion

        /// <summary>
        /// Returns the handle to the memory buffer.
        /// </summary>
        public IntPtr Handle
        {
            get
            {
                unsafe
                {
                    return (IntPtr)_ptr;
                }
            }
            set
            {
                unsafe
                {
                    _ptr = value.ToPointer();
                }
            }
        }

        /// <summary>
        /// Returns the pointer to the memory buffer.
        /// </summary>
        /// <returns></returns>
        public unsafe void* ToPointer()
        {
            return _ptr;
        }

        #region Indexers

        /// <summary>
        /// Sets the byte at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void byteAt(long index, byte value)
        {
            unsafe
            {
                *(byte*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the byte at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public byte byteAt(long index)
        {
            unsafe
            {
                return *(byte*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the signed byte at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void sbyteAt(long index, sbyte value)
        {
            unsafe
            {
                *(sbyte*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the signed byte at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public sbyte sbyteAt(long index)
        {
            unsafe
            {
                return *(sbyte*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the character at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void charAt(long index, char value)
        {
            unsafe
            {
                *(char*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the character at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public char charAt(long index)
        {
            unsafe
            {
                return *(char*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the Int16 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void shortAt(long index, short value)
        {
            unsafe
            {
                *(short*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the Int16 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public short shortAt(long index)
        {
            unsafe
            {
                return *(short*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the UInt16 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void ushortAt(long index, ushort value)
        {
            unsafe
            {
                *(ushort*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the UInt16 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public ushort ushortAt(long index)
        {
            unsafe
            {
                return *(ushort*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the Int32 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void intAt(long index, int value)
        {
            unsafe
            {
                *(int*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the Int32 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public int intAt(long index)
        {
            unsafe
            {
                return *(int*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the UInt32 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void uintAt(long index, uint value)
        {
            unsafe
            {
                *(uint*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the UInt32 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public uint uintAt(long index)
        {
            unsafe
            {
                return *(uint*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the Int64 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void longAt(long index, long value)
        {
            unsafe
            {
                *(long*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the Int64 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public long longAt(long index)
        {
            unsafe
            {
                return *(long*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the UInt64 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void ulongAt(long index, ulong value)
        {
            unsafe
            {
                *(ulong*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the UInt64 at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public ulong ulongAt(long index)
        {
            unsafe
            {
                return *(ulong*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the float at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void floatAt(long index, float value)
        {
            unsafe
            {
                *(float*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the float at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public float floatAt(long index)
        {
            unsafe
            {
                return *(float*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the double at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void doubleAt(long index, double value)
        {
            unsafe
            {
                *(double*)(((long)_ptr) + index) = value;
            }
        }
        
        /// <summary>
        /// Returns the double at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public double doubleAt(long index)
        {
            unsafe
            {
                return *(double*)(((long)_ptr) + index);
            }
        }
        
        /// <summary>
        /// Sets the decimal at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void decimalAt(long index, decimal value)
        {
            unsafe
            {
                *(decimal*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the decimal at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public decimal decimalAt(long index)
        {
            unsafe
            {
                return *(decimal*)(((long)_ptr) + index);
            }
        }

        /// <summary>
        /// Sets the System.Guid structure at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <param name="value">Value to set.</param>
        /// <returns></returns>
        public void GuidAt(long index, Guid value)
        {
            unsafe
            {
                *(Guid*)(((long)_ptr) + index) = value;
            }
        }

        /// <summary>
        /// Returns the System.Guid structure at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to start copying.</param>
        /// <returns></returns>
        public Guid GuidAt(long index)
        {
            unsafe
            {
                return *(Guid*)(((long)_ptr) + index);
            }
        }

        #endregion

        #region structures

        /// <summary>
        /// Copies the buffer to a structure of type T.
        /// </summary>
        /// <typeparam name="T">Type of structure to return.</typeparam>
        /// <returns></returns>
        public T ToStruct<T>() where T: struct
        {
            unsafe
            {
                if (_ptr == null) return new T();
                T x = (T)Marshal.PtrToStructure((IntPtr)_ptr, typeof(T));
                return x;
            }

        }

        /// <summary>
        /// Copies the contents of a structure of type T into the buffer.
        /// </summary>
        /// <typeparam name="T">Type of structure to copy.</typeparam>
        /// <param name="value">Structure to copy.</param>
        public void FromStruct<T>(T value) where T: struct
        {
            unsafe
            {
                if (_ptr == null)
                {
                    if(!Alloc(Marshal.SizeOf(new T()))) return;
                }
                Marshal.StructureToPtr(value, (IntPtr)_ptr, false);
            }
        }

        /// <summary>
        /// Gets the specified structure of type T at the specified byte index.
        /// </summary>
        /// <typeparam name="T">Type of structure to copy.</typeparam>
        /// <param name="index">Byte index at which to begin copying.</param>
        /// <returns></returns>
        public T GrabStructAt<T>(long index) where T : struct
        {
            unsafe
            {
                if (_ptr == null) return new T();
                T x = (T)Marshal.PtrToStructure((IntPtr)((void *)((ulong)_ptr + (ulong)index)), typeof(T));
                return x;
            }
        }

        /// <summary>
        /// Sets the specified structure of type T to the specified index.
        /// </summary>
        /// <typeparam name="T">Type of structure to copy.</typeparam>
        /// <param name="index">Byte index at which to begin copying.</param>
        /// <param name="value">Structure to copy.</param>
        public void SetStructAt<T>(long index, T value) where T : struct
        {
            unsafe
            {
                if (_ptr == null)
                {
                    if ((index != 0) || (!Alloc(Marshal.SizeOf(new T())))) return;
                }

                Marshal.StructureToPtr(value, (IntPtr)((void*)((ulong)_ptr + (ulong)index)), false);
            }
        }
        
        #endregion

        #region Bytes and Strings

        /// <summary>
        /// Sets the null terminated string at the specified byte index.
        /// If the pointer is null and the index != 0 then nothing happens.
        /// </summary>
        /// <param name="s">String to copy.</param>
        /// <param name="index">Byte index at which to begin copying.</param>
        public void SetString(string s, long index = 0)
        {
            s += (char)0;
            unsafe
            {
                if (_ptr == null)
                {
                    if ((index != 0) || (!Alloc(s.Length * 2))) return;
                }
                CopyMemory((void*)((long)(_ptr) + index), s, (IntPtr)(s.Length * 2));
            }
        }

        /// <summary>
        /// Returns the null-terminated string at the specified byte index.
        /// </summary>
        /// <param name="index">Index at which to begin copying.</param>
        /// <returns></returns>
        public string GrabString(long index = 0)
        {
            string o;

            unsafe
            {
                if (_ptr == null) return null;
                                
                char* c = (char*)((long)_ptr + index);
                char* orig = c;

                int i = 0;

                while (*c != (char)0)
                {
                    c++;
                    i++;
                }

                o = new string((char)0, i);
                CopyMemory(o, orig, (IntPtr)(i * 2));
            }

            return o;
        }

        /// <summary>
        /// Grabs a string at the specified byte index with the specified length.
        /// </summary>
        /// <param name="index">Byte index at which to begin copying.</param>
        /// <param name="length">Length, in UTF-16 characters.</param>
        /// <returns></returns>
        public string GrabString(long index, int length)
        {
            string s = new string((char)0, length);
            IntPtr l = (IntPtr)(length * 2);

            unsafe
            {
                if (_ptr == null) return null;

                void* lpsz = (void*)((long)_ptr + index);
                CopyMemory(s, lpsz, l);
            }

            return s;
        }

        /// <summary>
        /// Returns the contents of the buffer as a string from UTF-8 encoding.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public string GrabUtf8String(long index = 0)
        {
            byte[] o;

            unsafe
            {
                if (_ptr == null) return null;

                byte* c = (byte*)((long)_ptr + index);
                int i = 0;

                while (*c != (byte)0)
                {
                    c++;
                    i++;
                }

                o = new byte[i];
                CopyMemory(o, _ptr, (IntPtr)(i * 2));
            }

            return System.Text.Encoding.UTF8.GetString(o);
        }
        
        /// <summary>
        /// Grabs a BSTR-style COM string from the specified byte index.
        /// </summary>
        /// <param name="byteIndex">Index at which to begin copying.</param>
        /// <param name="comptr">Specifies whether this is an actual COM pointer.</param>
        /// <returns></returns>
        public string GrabBSTR(long byteIndex = 0, bool comptr = true)
        {
            unsafe
            {
                void* p = (comptr ? (void*)((ulong)_ptr + (ulong)byteIndex - 4) : (void*)((ulong)_ptr + (ulong)byteIndex));
                int i = 0;
                string s;

                i = *((int*)p);
                s = new string((char)0, i * 2);

                CopyMemory(s, (void*)((ulong)p + 4), (IntPtr)(i * 2));
                return s;
            }
        }
        
        /// <summary>
        /// Returns the string array at the byteIndex.
        /// </summary>
        /// <param name="byteIndex">Index at which to start copying.</param>
        /// <returns></returns>
        public string[] GrabStringArray(long byteIndex)
        {
            unsafe
            {

                if (_ptr == null) return null;

                string s = null;

                char *cp = (char*)((ulong)_ptr + (ulong)byteIndex);
                char *ap = cp;

                int x = 0;

                List<string> o = new List<string>();

                while (true)
                {

                    if (*ap == (char)0)
                    {
                        if (x != 0)
                        {
                            s = new String((char)0, x);
                            CopyMemory(s, cp, (IntPtr)(x * 2));
                            o.Add(s);

                            s = null;
                            x = 0;

                            ap++;
                            cp = ap;
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        x++;
                        ap++;
                    }
                }

                return o.ToArray();
            }
           
        }

        /// <summary>
        /// Grabs the specified byte array at the specified index with the specified length.
        /// </summary>
        /// <param name="index">Byte index at which to begin copying.</param>
        /// <param name="length">Number of bytes to copy, or 0 for the entire buffer.</param>
        /// <returns></returns>
        public byte[] GrabBytes(long index = 0, int length = 0)
        {
            byte[] b;

            unsafe
            {
                if (_ptr == null) return null;
                if (length == 0) length = (int)GetLength();

                void* p = (void*)((long)_ptr + index);
                b = new byte[length];
                CopyMemory(b, p, (IntPtr)length);
            }

            return b;
        }

        /// <summary>
        /// Sets the specified byte array to the specified byte index in the pointer
        /// If the pointer is null, a new memory buffer is allocated.
        /// If the pointer is null but the index is != 0 then nothing happens.
        /// </summary>
        /// <param name="value">The byte array to copy.</param>
        /// <param name="index">The byte index to begin copying.</param>
        public void SetBytes(byte[] value, int index = 0)
        {
            unsafe
            {
                if (_ptr == null)
                {
                    if ((index != 0) || (!Alloc(value.Length))) return;
                }

                CopyMemory((void*)((long)_ptr + index), value, (IntPtr)value.Length);
            }
        }

        /// <summary>
        /// Returns the contents of the memory pointer as a string.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return GrabString();
        }

        #endregion

        #region Allocation

        [DllImport("kernel32.dll")]
        private unsafe static extern void* HeapAlloc(void* hHeap, uint Flags, IntPtr size);

        [DllImport("kernel32.dll")]
        private unsafe static extern void* GetProcessHeap();

        [DllImport("kernel32.dll")]
        private unsafe static extern void* HeapReAlloc(void* hHeap, uint Flags, void* oldPtr, IntPtr newSize);

        [DllImport("kernel32.dll")]
        private unsafe static extern bool HeapFree(void* hHeap, uint Flags, void* ptr);

        [DllImport("kernel32.dll")]
        private unsafe static extern IntPtr HeapSize(void* hHeap, uint Flags, void* ptr);

        /// <summary>
        /// Gets the length of the currently allocated block of memory.
        /// This should only be called by a pointer that you know indicates the beginning of a
        /// block of memory allocated on the process heap.
        /// </summary>
        /// <returns></returns>
        public long GetLength()
        {
            unsafe
            {
                if (_ptr == null) return 0;
                return HeapSize(GetProcessHeap(), 0, _ptr).ToInt64();
            }
        }

        /// <summary>
        /// Allocates a block of memory on the process heap.
        /// </summary>
        /// <param name="size">Size of the buffer to allocate.</param>
        /// <returns>True if successful.</returns>
        public bool Alloc(long size)
        {
            unsafe
            {
                if (_ptr != null)
                {
                    if (size == GetLength()) return true;
                    return ReAlloc(size);
                }

                void* hheap = GetProcessHeap();
                _ptr = HeapAlloc(hheap, 8, new IntPtr(size));
                if (_ptr == null) return false;
                return true;
            }
        }

        /// <summary>
        /// Reallocate a block of memory on the process heap.
        /// </summary>
        /// <param name="size">New size of the memory block.</param>
        /// <returns>True if successful.</returns>
        public bool ReAlloc(long size)
        {
            unsafe
            {
                if (_ptr == null) return Alloc(size);

                if (GetLength() == size) return true;

                void* hheap = GetProcessHeap();
                void* n;

                n = HeapReAlloc(hheap, 8, _ptr, new IntPtr(size));
                if (n == null) return false;

                _ptr = n;
                return true;
            }
        }

        /// <summary>
        /// Frees a previously allocated block of memory.
        /// </summary>
        /// <returns></returns>
        public bool Free()
        {
            unsafe
            {
                if (_ptr == null) return true;

                void* hheap = GetProcessHeap();
                if (HeapFree(hheap, 0, _ptr))
                {
                    _ptr = null;
                    return true;
                }
                return false;
            }
        }

        #endregion Allocation

        #region Instantiation

        /// <summary>
        /// Initialize a new structure with the specified IntPtr as the handle.
        /// </summary>
        /// <param name="ptr">The IntPtr to assign.</param>
        public MemPtr(IntPtr ptr)
        {
            unsafe
            {
                _ptr = ptr.ToPointer();
            }
        }

        /// <summary>
        /// Initialize a new structure with the specified UIntPtr as the handle.
        /// </summary>
        /// <param name="ptr">The UIntPtr to assign.</param>
        public MemPtr(UIntPtr ptr)
        {
            unsafe
            {
                _ptr = ptr.ToPointer();
            }
        }

        /// <summary>
        /// Initialize a new structure with the specified pointer.
        /// </summary>
        /// <param name="ptr">The pointer to assign.</param>
        public unsafe MemPtr(void* ptr)
        {
            _ptr = ptr;
        }

        /// <summary>
        /// Initialize a new structure and allocate a new buffer of the specified size.
        /// </summary>
        /// <param name="size">The size of the new buffer.</param>
        public MemPtr(long size)
        {
            unsafe
            {
                _ptr = null;
            }
            Alloc(size);
        }

        #endregion

        #region Cast Operators

        // strings 

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator string(MemPtr operand)
        {
            return operand.GrabString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(string operand)
        {
            MemPtr mm = new MemPtr();
            mm.SetString(operand);
            return mm;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator string[](MemPtr operand)
        {
            return operand.GrabStringArray(0);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(string[] operand)
        {
            MemPtr mm = new MemPtr();
            long l = 0;
        
            foreach (string s in operand)
            {
                l += ((s.Length + 1) * 2);
            }
            l += 2;

            mm.Alloc(l);

            unsafe
            {
                void *sp = mm._ptr;

                foreach (string s in operand)
                {
                    l = (s.Length * 2);
                    CopyMemory(sp, s, (IntPtr)l);
                    sp = (void*)(((ulong)sp) + (ulong)l + 2);
                }

            }

            return mm;
        }

        // pointers

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static unsafe explicit operator void*(MemPtr operand)
        {
            return operand._ptr;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static unsafe explicit operator MemPtr(void* operand)
        {
            return new MemPtr(operand);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator IntPtr(MemPtr operand)
        {
            return operand.Handle;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(IntPtr operand)
        {
            return new MemPtr(operand);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator UIntPtr(MemPtr operand)
        {
            unsafe
            {
                return (UIntPtr)operand._ptr;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(UIntPtr operand)
        {
            return new MemPtr(operand);
        }

        // singletons

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator byte(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((byte*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(byte operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(1);
                *((byte*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator sbyte(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((sbyte*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(sbyte operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(1);
                *((sbyte*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator char(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return (char)0;
                return *((char*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(char operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(2);
                *((char*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator short(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((short*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(short operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(2);
                *((short*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator ushort(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((ushort*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(ushort operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(2);
                *((ushort*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator int(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((int*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(int operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(4);
                *((int*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator uint(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((uint*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(uint operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(4);
                *((uint*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator long(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((long*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(long operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(8);
                *((long*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator ulong(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((ulong*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(ulong operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(8);
                *((ulong*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator float(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((float*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(float operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(4);
                *((float*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator double(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((double*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(double operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(8);
                *((double*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator decimal(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return 0;
                return *((decimal*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(decimal operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(16);
                *((decimal*)mm._ptr) = operand;
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator Guid(MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return Guid.Empty;
                return *((Guid*)operand._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(Guid operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(16);
                *((Guid*)mm._ptr) = operand;
                return mm;
            }
        }

        // buffers

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator byte[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                byte[] o = new byte[operand.GetLength()];
                CopyMemory(o, operand._ptr, (IntPtr)o.Length);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(byte[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(operand.Length);
                CopyMemory(mm._ptr, operand, (IntPtr)operand.Length);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator sbyte[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                sbyte[] o = new sbyte[operand.GetLength()];
                CopyMemory(o, operand._ptr, (IntPtr)o.Length);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(sbyte[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                mm.Alloc(operand.Length);
                CopyMemory(mm._ptr, operand, (IntPtr)operand.Length);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator short[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 2) != 0) return null;

                short[] o = new short[l / 2];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(short[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 2;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator ushort[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 2) != 0) return null;

                ushort[] o = new ushort[l / 2];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(ushort[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 2;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator char[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 2) != 0) return null;

                char[] o = new char[l / 2];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(char[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 2;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator int[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 4) != 0) return null;

                int[] o = new int[l / 4];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(int[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 4;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator uint[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 4) != 0) return null;

                uint[] o = new uint[l / 4];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(uint[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 4;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator long[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 8) != 0) return null;

                long[] o = new long[l / 8];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(long[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 8;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator ulong[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 8) != 0) return null;

                ulong[] o = new ulong[l / 8];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(ulong[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 8;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator float[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 4) != 0) return null;

                float[] o = new float[l / 4];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(float[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 4;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator double[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 8) != 0) return null;

                double[] o = new double[l / 8];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(double[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 8;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator decimal[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 16) != 0) return null;

                decimal[] o = new decimal[l / 16];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(decimal[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 16;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator Guid[](MemPtr operand)
        {
            unsafe
            {
                if (operand._ptr == null) return null;
                long l = operand.GetLength();
                if ((l % 16) != 0) return null;

                Guid[] o = new Guid[l / 16];
                CopyMemory(o, operand._ptr, (IntPtr)l);
                return o;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand"></param>
        /// <returns></returns>
        public static implicit operator MemPtr(Guid[] operand)
        {
            unsafe
            {
                MemPtr mm = new MemPtr();
                long l = operand.Length * 16;
                mm.Alloc(l);
                CopyMemory(mm._ptr, operand, (IntPtr)l);
                return mm;
            }
        }

        #endregion

        #region Comparison Operators

        /// <summary>
        /// Tests whether or not this structure is equal to the specified object.
        /// </summary>
        /// <param name="obj">Object to compare.</param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if (obj.GetType() == typeof(MemPtr))
            {
                unsafe
                {
                    return (((MemPtr)obj)._ptr == _ptr);
                }
            }
            else if (obj.GetType() == typeof(IntPtr))
            {
                unsafe
                {
                    return (((IntPtr)obj).ToPointer() == _ptr);
                }
            }
            else if (obj.GetType() == typeof(UIntPtr))
            {
                unsafe
                {
                    return (((UIntPtr)obj).ToPointer() == _ptr);
                }
            }
            return false;
        }

        /// <summary>
        /// Returns the hashcode of this structure.
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            unsafe
            {
                int x = (int)(long)(_ptr);
                return (x >> 4) ^ -1;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator ==(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 == (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator ==(IntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 == (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator ==(MemPtr operand1, IntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 == (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator ==(UIntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 == (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator ==(MemPtr operand1, UIntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 == (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator !=(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 != (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator !=(IntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 != (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator !=(MemPtr operand1, IntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 != (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator !=(UIntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 != (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator !=(MemPtr operand1, UIntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 != (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator >(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 > (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator >(IntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 > (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator >(MemPtr operand1, IntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 > (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator >(UIntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 > (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator >(MemPtr operand1, UIntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 > (void*)operand2);
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator <(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 < (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator <(IntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 < (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator <(MemPtr operand1, IntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 < (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator <(UIntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 < (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator <(MemPtr operand1, UIntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 < (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator >=(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 >= (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator >=(IntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 >= (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator >=(MemPtr operand1, IntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 >= (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator >=(UIntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 >= (void*)operand2);
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator >=(MemPtr operand1, UIntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 >= (void*)operand2);
            }
        }
                
        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator <=(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 <= (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator <=(IntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 <= (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator <=(MemPtr operand1, IntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 <= (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator <=(UIntPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 <= (void*)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static bool operator <=(MemPtr operand1, UIntPtr operand2)
        {
            unsafe
            {
                return ((void*)operand1 <= (void*)operand2);
            }
        }
        
        #endregion

        #region Pointer Arithmatic

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr + (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr - (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr * (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr / (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(MemPtr operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr % (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(MemPtr operand1, short operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr + (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(MemPtr operand1, ushort operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr + (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(short operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 + (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(ushort operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 + (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(MemPtr operand1, short operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr - (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(MemPtr operand1, ushort operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr - (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(short operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 - (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(ushort operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 - (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(MemPtr operand1, short operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr * (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(MemPtr operand1, ushort operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr * (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(short operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 * (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(ushort operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 * (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(MemPtr operand1, short operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr / (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(MemPtr operand1, ushort operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr / (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(short operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 / (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(ushort operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 / (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(MemPtr operand1, short operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr % (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(MemPtr operand1, ushort operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr % (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(short operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 % (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(ushort operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 % (ulong)operand2._ptr);
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(MemPtr operand1, int operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr + (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(MemPtr operand1, uint operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr + (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(int operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 + (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(uint operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 + (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(MemPtr operand1, int operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr - (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(MemPtr operand1, uint operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr - (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(int operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 - (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(uint operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 - (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(MemPtr operand1, int operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr * (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(MemPtr operand1, uint operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr * (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(int operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 * (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(uint operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 * (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(MemPtr operand1, int operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr / (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(MemPtr operand1, uint operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr / (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(int operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 / (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(uint operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 / (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(MemPtr operand1, int operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr % (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(MemPtr operand1, uint operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr % (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(int operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 % (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(uint operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 % (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(MemPtr operand1, long operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr + (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(MemPtr operand1, ulong operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr + (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(long operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 + (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator +(ulong operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 + (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(MemPtr operand1, long operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr - (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(MemPtr operand1, ulong operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr - (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(long operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 - (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator -(ulong operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 - (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(MemPtr operand1, long operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr * (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(MemPtr operand1, ulong operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr * (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(long operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 * (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator *(ulong operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 * (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(MemPtr operand1, long operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr / (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(MemPtr operand1, ulong operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr / (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(long operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 / (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator /(ulong operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 / (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(MemPtr operand1, long operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr % (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(MemPtr operand1, ulong operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1._ptr % (ulong)operand2);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(long operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 % (ulong)operand2._ptr);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="operand1"></param>
        /// <param name="operand2"></param>
        /// <returns></returns>
        public static MemPtr operator %(ulong operand1, MemPtr operand2)
        {
            unsafe
            {
                return (MemPtr)(void*)((ulong)operand1 % (ulong)operand2._ptr);
            }
        }

        #endregion

    }


    #endregion

}